import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { NzFormatEmitEvent } from 'ng-zorro-antd/core';
import {
  ControlUIWidget,
  SFSchemaEnum,
  SFTreeSelectWidgetSchema,
  SFValue,
  SFSchema,
  SFUISchemaItem,
} from '@delon/form';
import { toBoolean, deepCopy } from '@delon/util';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';

export function isBlank(o: any) {
  return o == null;
}

export function toBool(value: any, defaultValue: boolean) {
  value = toBoolean(value, true);
  return value == null ? defaultValue : value;
}

export function getData(
  schema: SFSchema,
  ui: SFUISchemaItem,
  formData: any,
  asyncArgs?: any,
): Observable<SFSchemaEnum[]> {
  if (typeof ui.asyncData === 'function') {
    return ui.asyncData(asyncArgs).pipe(map((list: SFSchemaEnum[]) => getEnum(list, formData, schema.readOnly!)));
  }
  return of(getCopyEnum(schema.enum!, formData, schema.readOnly!));
}

export function getEnum(list: any[], formData: any, readOnly: boolean): SFSchemaEnum[] {
  if (isBlank(list) || !Array.isArray(list) || list.length === 0) return [];
  if (typeof list[0] !== 'object') {
    list = list.map((item: any) => {
      return { label: item, value: item } as SFSchemaEnum;
    });
  }
  if (formData) {
    if (!Array.isArray(formData)) formData = [formData];
    list.forEach((item: SFSchemaEnum) => {
      if (~formData.indexOf(item.value)) item.checked = true;
    });
  }
  // fix disabled status
  if (readOnly) {
    list.forEach((item: SFSchemaEnum) => (item.disabled = true));
  }
  return list;
}

export function getCopyEnum(list: any[], formData: any, readOnly: boolean) {
  return getEnum(deepCopy(list || []), formData, readOnly);
}

@Component({
  selector: 'sf-tree-select2',
  templateUrl: './tree-select.widget.html',
  preserveWhitespaces: false,
  encapsulation: ViewEncapsulation.None,
})
export class TreeSelectWidget2 extends ControlUIWidget<SFTreeSelectWidgetSchema> implements OnInit {
  static readonly KEY = 'sf-tree-select2';
  i: any;
  data: SFSchemaEnum[] = [];

  ngOnInit(): void {
    const { ui } = this;
    this.i = {
      allowClear: ui.allowClear,
      showSearch: toBool(ui.showSearch, false),
      dropdownMatchSelectWidth: toBool(ui.dropdownMatchSelectWidth, true),
      multiple: toBool(ui.multiple, false),
      checkable: toBool(ui.checkable, false),
      showExpand: toBool(ui.showExpand, true),
      showLine: toBool(ui.showLine, false),
      asyncData: typeof ui.expandChange === 'function',
      defaultExpandAll: toBool(ui.defaultExpandAll, false),
      defaultExpandedKeys: ui.defaultExpandedKeys || [],
      displayWith: ui.displayWith || ((node: any) => node.title),
    };
  }

  reset(value: SFValue) {
    getData(this.schema, this.ui, value).subscribe(list => {
      this.data = list;
      this.detectChanges();
    });
  }

  change(value: string[] | string) {
    if (this.ui.change) this.ui.change(value);
    this.setValue(value);
  }

  expandChange(e: NzFormatEmitEvent) {
    const { ui } = this;
    if (typeof ui.expandChange !== 'function') return;
    ui.expandChange(e).subscribe(res => {
      e.node!.clearChildren();
      e.node!.addChildren(res);
      this.detectChanges();
    });
  }
}
